<?php


namespace app\common\service\platform;


use app\common\library\Tools;
use app\common\model\Account;
use app\common\model\Orders;
use app\common\model\OrdersTemp;
use app\common\service\BaseService;
use PDOStatement;
use think\Collection;
use think\facade\Log;

/**
 * 平台接口对接基类
 * Class BasePlatformService
 * @package app\common\service\platform
 */
abstract class BasePlatformService extends BaseService
{
    /**
     * 账号 id
     * @var int
     */
    protected $accountId;

    /**
     * api 基础 url
     * @var string
     * @example http://gw.api.alibaba.com
     */
    protected $baseUrl;

    /**
     * 时区偏移量
     * @var int
     */
    protected $offsetDate = 0;

    /**
     * token 字段约束
     * @var array
     */
    public static $tokenField = [
        'required' => [], // 必填字段
        'option' => [], // 可选字段
    ];

    /**
     * 账号
     * @var Account
     */
    protected $account;

    public function __construct($accountId = 0)
    {
        $this->accountId = $accountId;
        $this->account = $this->getAccountById($accountId);
        $this->baseUrl = rtrim($this->account->platform->api_base_url, "/");
        $this->init();
    }

    /**
     * 检测对接平台类是否存在
     * @param string $className 类名，不需要全类名
     * @return bool
     * @date 2020/09/17
     * @author longli
     */
    public static function classesExist($className = '')
    {
        if(!Tools::startWith($className, '\\')) $className = static::getClasses($className);
        return class_exists($className);
    }

    /**
     * 获取对接平台的全类名
     * @param string $className 类名
     * @return string
     * @date 2020/09/17
     * @author longli
     */
    public static function getClasses($className = '')
    {
        return '\app\common\service\platform\\' . $className;
    }

    /**
     * 初始化方法
     * @date 2020/08/26
     * @author longli
     */
    public function init(){}

    /**
     * 添加平台订单到临时表
     * @param string $orderNo 平台订单号
     * @param array $order 订单信息
     * @param bool $replace 存在是否替换，默认不替换
     * @date 2020/08/20
     * @return bool
     * @author longli
     */
    public function pushOrderToTemp($orderNo, $order = [], $replace = false)
    {
        // 如果订单已存在则直接跳过
        $hasOrder = OrdersTemp::hasOrder($orderNo, $this->getAccountId());
        if(!$replace && $hasOrder) return false;
        if($replace && $hasOrder)
        {
            OrdersTemp::get([
                "order_no" => $orderNo,
                "account_id" => $this->getAccountId()
            ])->save([
                "is_sync_order" => OrdersTemp::SYNC_ORDER_N,
                "order_info" => json_encode($order),
            ]);
        }
        else
        {
            OrdersTemp::create([
                "order_no" => $orderNo,
                "account_id" => $this->getAccountId(),
                "site" => $this->getAccount()->site,
                "order_info" => json_encode($order),
            ]);
        }
        return true;
    }

    /**
     * 同步一条订单数据
     * @param OrdersTemp $ordersTemp 一条订单数据
     * @date 2020/08/20
     * @return bool
     *@author longli
     */
    abstract public function syncOrder(OrdersTemp $ordersTemp);

    abstract public function getOrderList($params = [], $replace = false);

    /**
     * 同步订单到 order 表
     * @param int[]|int $accountId 账号id, 同步指定账号订单， 默认同步所有订单
     * @param string $startDate 从什么时间开始同步，默认是所有
     * @param bool $force 是否强制同步，默认不强制同步
     * @date 2020/08/20
     * @author longli
     */
    public function syncOrderByAccount($accountId = [], $startDate = null, $force = false)
    {
        Log::info(sprintf("通过账号同步订单到订单表，参数: 【%s】", json_encode(func_get_args())));
        $where = [];
        if(!$force) $where[] = ['is_sync_order', '=', OrdersTemp::SYNC_ORDER_N];
        if(!empty($accountId))$where[] = ['account_id', 'in', $accountId];
        if(!empty($startDate)) $where[] = ['create_time', '>=', $startDate];
        OrdersTemp::where($where)->chunk(1000, function($result)
        {
            foreach($result as $item)
            {
                if($this->syncOrder($item))
                {
                    $item->is_sync_order = OrdersTemp::SYNC_ORDER_Y;
                    $item->sync_time = Tools::now();
                    $item->save();
                }
            }
        });
    }

    /**
     * 平台标记订单发货, 标记当前账号下指定的订单
     * @param int|int[] $orderIds 订单 id, 默认为空，标记当前账号下所有未标记的订单
     * @date 2020/08/24
     * @author longli
     */
    public function markDelivery($orderIds = [])
    {}

    /**
     * 获取需要标记的订单
     * @param array $orderIds
     * @return array|PDOStatement|string|Collection
     * @date 2020/08/27
     * @author longli
     */
    public function getNeedMarkOrders($orderIds = [])
    {
        $where = [
            ["account_id", "eq", $this->getAccountId()],
            ["is_flag_sent", "eq", Orders::FLAG_SENT_NO],
            ["track_num", "neq", ""]
        ];
        if(!empty($orderIds)) $where[] = ["order_id", "in", $orderIds];
        return Orders::where($where)->with(['details', 'account'])->select();
    }

    /**
     * 通过平台同步订单
     * @param string[] $platform 平台名称
     * @param string $startDate 从什么时间开始同步，默认是所有
     * @param bool $force 是否强制同步，默认不强制同步
     * @date 2020/08/20
     * @author longli
     */
    public function syncOrderByPlatform($platform = [], $startDate = null, $force = false)
    {
        // @todo
    }

    /**
     * 通过 Id 同步订单
     * @param int[] $ids order_temp id
     * @param bool $force 是否强制同步，默认不强制同步
     * @date 2020/08/20
     * @author longli
     */
    public function syncOrderById($ids = [], $force = false)
    {
        if(!is_array($ids)) $ids = [$ids];
        Log::info(sprintf("通过 id 同步订单到订单表，参数: 【%s】", json_encode(func_get_args())));
        $where = [["temp_id", 'in', $ids]];
        if(!$force) $where[] = ['is_sync_order', '=', OrdersTemp::SYNC_ORDER_N];
        foreach (OrdersTemp::where($where)->select() as $item)
        {
            if($this->syncOrder($item))
            {
                $item->is_sync_order = OrdersTemp::SYNC_ORDER_Y;
                $item->sync_time = Tools::now();
                $item->save();
            }
        }
    }

    /**
     * 格式时间为 ISO8601 格式
     * @param string $time 时间戳，或者字符时间，默认为当前时间
     * @param string $suffix 后缀
     * @date 2020/08/19
     * @author longli
     * @return string
     */
    public function formatTimeToDate($time = '', $suffix = '')
    {
        $time = $time ?: time();
        if(!is_numeric($time)) $time = strtotime($time);
        return str_replace(' ', 'T' , date('Y-m-d H:i:s', $time)) . $suffix;
    }

    /**
     * 解析 ISO8601 格式时间为中国时间
     * @param string $time 时间
     * @param int $offset 时区偏移 date('Z')
     * @date 2020/08/19
     * @author longli
     * @return string
     */
    public function parseTimeToDate($time, $offset = 0)
    {
        if(is_numeric($time) && strlen($time) == 13) $time = intval($time / 1000);
        if(!is_numeric($time) && strtotime($time) === false) return null;
        return date('Y-m-d H:i:s', (is_numeric($time) ? $time : strtotime($time)) - $offset);
    }

    /**
     * 获取所有平台对接 Service 服务
     * @return array
     * @date 2020/09/24
     * @author longli
     */
    public static function getAllPlatformService()
    {
        return self::getAllService(__DIR__, Tools::classBasename(__CLASS__));
    }

    /**
     * @param int $accountId
     */
    public function setAccountId($accountId)
    {
        $this->accountId = $accountId;
    }

    /**
     * @return int
     */
    public function getAccountId()
    {
        return $this->accountId;
    }

    /**
     * @return string
     */
    public function getBaseUrl()
    {
        return $this->baseUrl;
    }

    /**
     * @param string $baseUrl
     */
    public function setBaseUrl($baseUrl)
    {
        $this->baseUrl = $baseUrl;
    }

    /**
     * @return Account
     */
    public function getAccount()
    {
        return $this->account;
    }

    /**
     * @param Account $account
     */
    public function setAccount($account)
    {
        $this->account = $account;
    }
}